package com.cloud.common.rpc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloud.common.bean.SessionInfo;
import com.cloud.common.context.MappingContext;
import com.cloud.common.context.RequestMapping;
import com.cloud.common.context.SessionHolder;
import com.cloud.common.context.VersionHolder;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.LinkedHashMap;

@Sharable
@Component
public class ServerHandler extends SimpleChannelInboundHandler<Message> {

    @Autowired
    private MappingContext mappingContext;

    @Autowired
    private VersionHolder versionHolder;

    @Autowired
    private SessionHolder sessionHolder;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
        Request request = JSON.parseObject(msg.getBodyData(), Request.class);
        RequestMapping requestMapping = mappingContext.getRequestMapping(request.getRequestUri());
        if (requestMapping != null) {
            versionHolder.set(request.getVersionInfo());
            sessionHolder.set(JSON.parseObject(request.getSessionInfo(), SessionInfo.class));

            //设置方法参数
            int index = 0;
            LinkedHashMap<String, Class> parameterMap = requestMapping.getParameterMap();
            Iterator<String> itor = parameterMap.keySet().iterator();
            Object[] params = new Object[parameterMap.size()];
            JSONObject requestParam = JSON.parseObject(request.getRequestParam());
            while (itor.hasNext()) {
                String name = itor.next();
                Class clazz = parameterMap.get(name);
                params[index] = requestParam.getObject(name, clazz);
                index++;
            }

            //反射调用方法
            Object target = requestMapping.getHandlerTarget();
            Method method = requestMapping.getHandlerMethod().getMethod();
            Object result = method.invoke(target, params);

            //返回结果
            Message resMsg = new Message(JSON.toJSONString(result));
            resMsg.setSequence(msg.getSequence());
            ctx.channel().writeAndFlush(resMsg);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)  throws Exception {
        ctx.close();
    }
}
